package user

import (
	"fmt"
	"net/http"
	"server/config"
	model "server/model/user"
	"server/utils"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"golang.org/x/crypto/bcrypt"
)

var tableName = "user"

// RegisterUser 注册用户（当前路由未启用）
func RegisterUser(c *gin.Context) {
	var req model.User
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	if req.Password == "" {
		utils.JSONResponse(c, http.StatusBadRequest, "验证失败：密码不能为空", nil)
		return
	}
	if !utils.ValidateStruct(c, &req) {
		return
	}
	// 检查用户名是否被占用
	exists, err := utils.CheckTableExist(tableName, "username", req.Username)
	if err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("注册失败: %v", err), nil)
		return
	}
	if exists {
		utils.JSONResponse(c, http.StatusBadRequest, "用户名已被占用", nil)
		return
	}
	// 加密密码并写入
	hashed, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("注册失败: %v", err), nil)
		return
	}
	req.Password = string(hashed)
	sqlStr := fmt.Sprintf("INSERT INTO %s (username, password) VALUES (?, ?)", tableName)
	if _, err = utils.DB.Exec(sqlStr, req.Username, req.Password); err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("注册失败: %v", err), nil)
		return
	}
	utils.JSONResponse(c, http.StatusOK, "注册成功", nil)
}

// LoginUser 登录
func LoginUser(c *gin.Context) {
	var req model.User
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	// 检查用户名是否存在
	exists, err := utils.CheckTableExist(tableName, "username", req.Username)
	if err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("登录失败: %v", err), nil)
		return
	}
	if !exists {
		utils.JSONResponse(c, http.StatusBadRequest, "用户名不存在", nil)
		return
	}
	// 查询用户信息
	sqlStr := fmt.Sprintf("SELECT id,username,password,name,mobile,email,avatar,role,create_time,is_deleted FROM %s WHERE username = ?", tableName)
	var userInfo model.User
	if err := utils.DB.QueryRow(sqlStr, req.Username).Scan(&userInfo.Id, &userInfo.Username, &userInfo.Password, &userInfo.Name, &userInfo.Mobile, &userInfo.Email, &userInfo.Avatar, &userInfo.Role, &userInfo.CreateTime, &userInfo.IsDeleted); err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("登录失败: %v", err), nil)
		return
	}
	// 校验密码与状态
	if err := bcrypt.CompareHashAndPassword([]byte(userInfo.Password), []byte(req.Password)); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, "密码错误", nil)
		return
	}
	if userInfo.IsDeleted == 1 {
		utils.JSONResponse(c, http.StatusBadRequest, "账户已注销", nil)
		return
	}
	if userInfo.Role != 0 {
		utils.JSONResponse(c, http.StatusBadRequest, "用户权限不足", nil)
		return
	}
	// 生成 token
	claims := jwt.MapClaims{
		"user_id": userInfo.Id,
		"exp":     time.Now().Add(time.Hour * 24 * 7).Unix(),
	}
	token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(config.Jwt.Secret))
	if err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("登录失败: %v", err), nil)
		return
	}
	userInfo.Password = ""
	utils.JSONResponse(c, http.StatusOK, "登录成功", gin.H{
		"token":    token,
		"userInfo": userInfo,
	})
}

// CreateUser 创建用户
func CreateUser(c *gin.Context) {
	var req model.User
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	if req.Password == "" {
		utils.JSONResponse(c, http.StatusBadRequest, "验证失败：密码不能为空", nil)
		return
	}
	if !utils.ValidateStruct(c, &req) {
		return
	}
	// 唯一性检查
	if exists, err := utils.CheckTableExist(tableName, "username", req.Username); err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("创建用户失败: %v", err), nil)
		return
	} else if exists {
		utils.JSONResponse(c, http.StatusBadRequest, "用户名已被占用", nil)
		return
	}
	if req.Mobile != "" {
		if exists, err := utils.CheckTableExist(tableName, "mobile", req.Mobile); err != nil {
			utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("创建用户失败: %v", err), nil)
			return
		} else if exists {
			utils.JSONResponse(c, http.StatusBadRequest, "手机号已被占用", nil)
			return
		}
	}
	if req.Email != "" {
		if exists, err := utils.CheckTableExist(tableName, "email", req.Email); err != nil {
			utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("创建用户失败: %v", err), nil)
			return
		} else if exists {
			utils.JSONResponse(c, http.StatusBadRequest, "邮箱已被占用", nil)
			return
		}
	}
	hashed, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("创建用户失败: %v", err), nil)
		return
	}
	req.Password = string(hashed)
	sqlStr := fmt.Sprintf("INSERT INTO %s (username, password, name, mobile, email, avatar) VALUES (?, ?, ?, ?, ?, ?)", tableName)
	if _, err = utils.DB.Exec(sqlStr, req.Username, req.Password, req.Name, req.Mobile, req.Email, req.Avatar); err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("创建用户失败: %v", err), nil)
		return
	}
	utils.JSONResponse(c, http.StatusOK, "创建用户成功", nil)
}

// UpdateUser 更新用户
func UpdateUser(c *gin.Context) {
	var req model.User
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	if !utils.ValidateStruct(c, &req) {
		return
	}
	// 检查用户是否存在
	if exists, err := utils.CheckTableExist(tableName, "id", req.Id); err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("更新用户信息失败: %v", err), nil)
		return
	} else if !exists {
		utils.JSONResponse(c, http.StatusBadRequest, "用户不存在", nil)
		return
	}
	// 查询当前用户信息
	var current model.User
	if err := utils.DB.QueryRow(
		fmt.Sprintf("SELECT id,username,password,name,mobile,email,avatar,role,create_time,is_deleted FROM %s WHERE id = ?", tableName),
		req.Id,
	).Scan(&current.Id, &current.Username, &current.Password, &current.Name, &current.Mobile, &current.Email, &current.Avatar, &current.Role, &current.CreateTime, &current.IsDeleted); err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("更新用户信息失败: %v", err), nil)
		return
	}
	// 唯一性检查
	if current.Username != req.Username {
		if exists, err := utils.CheckTableExist(tableName, "username", req.Username); err != nil {
			utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("更新用户信息失败: %v", err), nil)
			return
		} else if exists {
			utils.JSONResponse(c, http.StatusBadRequest, "用户名已被占用", nil)
			return
		}
	}
	if current.Email != req.Email {
		if exists, err := utils.CheckTableExist(tableName, "email", req.Email); err != nil {
			utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("更新用户信息失败: %v", err), nil)
			return
		} else if exists {
			utils.JSONResponse(c, http.StatusBadRequest, "邮箱已被占用", nil)
			return
		}
	}
	if current.Mobile != req.Mobile {
		if exists, err := utils.CheckTableExist(tableName, "mobile", req.Mobile); err != nil {
			utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("更新用户信息失败: %v", err), nil)
			return
		} else if exists {
			utils.JSONResponse(c, http.StatusBadRequest, "手机号已被占用", nil)
			return
		}
	}
	// 更新
	if _, err := utils.DB.Exec(
		fmt.Sprintf("UPDATE %s SET username = ?, name = ?, mobile = ?, email = ?, avatar = ? WHERE id = ?", tableName),
		req.Username, req.Name, req.Mobile, req.Email, req.Avatar, req.Id,
	); err != nil {
		utils.JSONResponse(c, http.StatusInternalServerError, fmt.Sprintf("更新用户信息失败: %v", err), nil)
		return
	}
	utils.JSONResponse(c, http.StatusOK, "更新用户信息成功", nil)
}

// GetUserDetail 获取用户信息
func GetUserDetail(c *gin.Context) {
	var req model.User
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	// 查询用户信息（支持 id 或 username）
	sqlStr := fmt.Sprintf("SELECT id,username,password,name,mobile,email,avatar,role,create_time,is_deleted FROM %s WHERE 1=1", tableName)
	var args []interface{}
	if req.Id != 0 {
		sqlStr += " AND id = ?"
		args = append(args, req.Id)
	} else if req.Username != "" {
		sqlStr += " AND username = ?"
		args = append(args, req.Username)
	}
	var userInfo model.User
	if err := utils.DB.QueryRow(sqlStr, args...).Scan(&userInfo.Id, &userInfo.Username, &userInfo.Password, &userInfo.Name, &userInfo.Mobile, &userInfo.Email, &userInfo.Avatar, &userInfo.Role, &userInfo.CreateTime, &userInfo.IsDeleted); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("获取用户信息失败: %v", err), nil)
		return
	}
	userInfo.Password = ""
	utils.JSONResponse(c, http.StatusOK, "获取用户信息成功", userInfo)
}

// GetUserList 获取用户列表
func GetUserList(c *gin.Context) {
	var req model.Query
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	var (
		args       []interface{}
		conditions []string
		result     = model.List{}
	)
	if req.Username != "" {
		conditions = append(conditions, "username LIKE ?")
		args = append(args, "%"+req.Username+"%")
	}
	if req.Mobile != "" {
		conditions = append(conditions, "mobile = ?")
		args = append(args, req.Mobile)
	}
	if req.Email != "" {
		conditions = append(conditions, "email = ?")
		args = append(args, req.Email)
	}
	if req.IsDeleted != nil {
		conditions = append(conditions, "is_deleted = ?")
		args = append(args, *req.IsDeleted)
	} else {
		conditions = append(conditions, "is_deleted = ?")
		args = append(args, 0)
	}

	countSQL := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE 1=1", tableName)
	if len(conditions) > 0 {
		countSQL += " AND " + strings.Join(conditions, " AND ")
	}
	if err := utils.DB.QueryRow(countSQL, args...).Scan(&result.Total); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("获取用户列表失败: %v", err), nil)
		return
	}

	pageNum := 1
	pageSize := 100
	if req.PageNum != nil && *req.PageNum > 0 {
		pageNum = *req.PageNum
	}
	if req.PageSize != nil && *req.PageSize > 0 {
		if *req.PageSize > 100 {
			pageSize = 100
		} else {
			pageSize = *req.PageSize
		}
	}
	offset := (pageNum - 1) * pageSize

	querySQL := fmt.Sprintf("SELECT id, username, name, mobile, email, avatar, role, is_deleted FROM %s WHERE 1=1", tableName)
	if len(conditions) > 0 {
		querySQL += " AND " + strings.Join(conditions, " AND ")
	}
	querySQL += " ORDER BY id DESC"
	querySQL += " LIMIT ? OFFSET ?"
	args = append(args, pageSize, offset)

	rows, err := utils.DB.Query(querySQL, args...)
	if err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("获取用户列表失败: %v", err), nil)
		return
	}
	defer rows.Close()

	var users []model.User = []model.User{}
	for rows.Next() {
		var u model.User
		if err := rows.Scan(&u.Id, &u.Username, &u.Name, &u.Mobile, &u.Email, &u.Avatar, &u.Role, &u.IsDeleted); err != nil {
			utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("获取用户列表失败: %v", err), nil)
			return
		}
		users = append(users, u)
	}
	result.List = users
	utils.JSONResponse(c, http.StatusOK, "获取用户列表成功", result)
}

// ResetPassword 重置密码
func ResetPassword(c *gin.Context) {
	var req model.User
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	if req.Password == "" {
		req.Password = "123456"
	}
	if exists, err := utils.CheckTableExist(tableName, "id", req.Id); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("重置密码失败: %v", err), nil)
		return
	} else if !exists {
		utils.JSONResponse(c, http.StatusBadRequest, "用户不存在", nil)
		return
	}
	hashed, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("重置密码失败: %v", err), nil)
		return
	}
	if _, err := utils.DB.Exec("UPDATE user SET password = ? WHERE id = ?", string(hashed), req.Id); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("重置密码失败: %v", err), nil)
		return
	}
	utils.JSONResponse(c, http.StatusOK, fmt.Sprintf("密码重置为：%s", req.Password), nil)
}

// LogoutUser 注销用户
func LogoutUser(c *gin.Context) {
	var req model.User
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	if exists, err := utils.CheckTableExist(tableName, "id", req.Id); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("注销用户失败: %v", err), nil)
		return
	} else if !exists {
		utils.JSONResponse(c, http.StatusBadRequest, "用户不存在", nil)
		return
	}
	if _, err := utils.DB.Exec("UPDATE user SET is_deleted = 1 WHERE id = ?", req.Id); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("注销用户失败: %v", err), nil)
		return
	}
	utils.JSONResponse(c, http.StatusOK, "注销用户成功", nil)
}

// RecoverUser 恢复用户
func RecoverUser(c *gin.Context) {
	var req model.User
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	if exists, err := utils.CheckTableExist(tableName, "id", req.Id); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("恢复用户失败: %v", err), nil)
		return
	} else if !exists {
		utils.JSONResponse(c, http.StatusBadRequest, "用户不存在", nil)
		return
	}
	if _, err := utils.DB.Exec("UPDATE user SET is_deleted = 0 WHERE id = ?", req.Id); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("恢复用户失败: %v", err), nil)
		return
	}
	utils.JSONResponse(c, http.StatusOK, "恢复用户成功", nil)
}

// ChangePassword 修改密码
func ChangePassword(c *gin.Context) {
	var req model.ChangePassword
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("请求格式或字段不合法: %v", err), nil)
		return
	}
	if !utils.ValidateStruct(c, &req) {
		return
	}
	if currentUserId, ok := c.Get("user_id"); ok {
		req.Id = currentUserId.(int)
	} else {
		utils.JSONResponse(c, http.StatusUnauthorized, "身份验证失败！", nil)
		return
	}
	if exists, err := utils.CheckTableExist(tableName, "id", req.Id); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("修改密码失败: %v", err), nil)
		return
	} else if !exists {
		utils.JSONResponse(c, http.StatusBadRequest, "用户不存在", nil)
		return
	}
	// 查询当前用户密码
	var userInfo model.User
	if err := utils.DB.QueryRow(
		fmt.Sprintf("SELECT id,username,password,name,mobile,email,avatar,role,create_time,is_deleted FROM %s WHERE id = ?", tableName),
		req.Id,
	).Scan(&userInfo.Id, &userInfo.Username, &userInfo.Password, &userInfo.Name, &userInfo.Mobile, &userInfo.Email, &userInfo.Avatar, &userInfo.Role, &userInfo.CreateTime, &userInfo.IsDeleted); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("修改密码失败: %v", err), nil)
		return
	}
	if err := bcrypt.CompareHashAndPassword([]byte(userInfo.Password), []byte(req.Password)); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, "旧密码错误", nil)
		return
	}
	hashed, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
	if err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("修改密码失败: %v", err), nil)
		return
	}
	if _, err := utils.DB.Exec("UPDATE user SET password = ? WHERE id = ?", string(hashed), req.Id); err != nil {
		utils.JSONResponse(c, http.StatusBadRequest, fmt.Sprintf("修改密码失败: %v", err), nil)
		return
	}
	utils.JSONResponse(c, http.StatusOK, "密码修改成功", nil)
}


